#ifndef INSTRSTREAM_H
#define INSTRSTREAM_H

#define MAX_OPCOUNT 3

typedef  unsigned int OpType ;

#define OP_FLAG_TYPE_NULL               0x00
#define	OP_FLAG_TYPE_INT    		    0x01
#define	OP_FLAG_TYPE_FLOAT  		    0x02
#define	OP_FLAG_TYPE_STRING 		    0x04
#define	OP_FLAG_TYPE_INSTR_INDEX	    0x08
#define	OP_FLAG_TYPE_ABS_STACK_INDEX        0x10	
#define	OP_FLAG_TYPE_REL_STACK_INDEX        0x20	
#define	OP_FLAG_TYPE_MEM_REF    	    0x40
#define	OP_FLAG_TYPE_FUNC_INDEX	            0x80
#define	OP_FLAG_TYPE_HOST_API_CALL 	    0x100
#define	OP_FLAG_TYPE_REG 	           0x200

#define	OP_FLAG_TYPE_KEY_FRAME              0x800
#define	OP_FLAG_TYPE_TOP_FRAME              0x1000
#define	OP_FLAG_TYPE_STACK_MARKER           0x2000


typedef unsigned char CODE;
typedef unsigned char COUNT;


struct Value {
	OpType _type;
	union {
		int   vint;
		float vfloat;
		int   vindex;
	} _value;

	string  _svalue;
	int     _offset;

#define _vint _value.vint
#define _vfloat _value.vfloat 
#define _vindex _value.vindex
};

struct AuxInstr {
	CODE   _opCode;
	COUNT  _opCount;
	OpType _opList[MAX_OPCOUNT];
};


struct Instr {
	CODE    _opCode;
	COUNT   _opCount;
	Value   _valList[MAX_OPCOUNT];
};	


class InstrStream {
public:
	InstrStream() { 
		if (loadConfig("..\\config\\instruction.ini")) 
		      printf("Instruction config file instruction.txt not exist!\n");
	}

	const string &codeName(CODE opcode);
	CODE  nameCode(const string &name);
	COUNT getOpCount(const string &name) { return _instrConfig[name]._opCount; }
	OpType getOpType(const string &name, int index) { return _instrConfig[name]._opList[index]; }
	int   loadConfig(const char *file);

	void  instrList(vector<string> &instrs);
	int   addInstruction(Instr &instr) { _instrStream.push_back(instr); return _instrStream.size()-1; }
	Instr& getInstruction(int index);

	int   readFile(FILE *fp, const StringTable &st);
	int   writeFile(FILE *fp);

	void  dump();
    char *dumpLine(int line);

    static const char *valueDump(Value &val);
private:
	int  cfgAdd(const string &name, CODE opcode, COUNT opcount);
	int  cfgSetOpType(const string &name, int opindex, OpType &op);

private:
	map<CODE, string>	  _code2Name;
	map<string, CODE> 	  _name2Code;
	vector<Instr>    	  _instrStream;
	map<string, AuxInstr>     _instrConfig;
};


#endif
